using System;
using System.Collections;
using System.Data;
using System.Web.UI.WebControls;
using PHSRAG.Insight21.Common.Pages;
using PHSRAG.Insight21.Context;
using PHSRAG.Insight21.InsightWorkFlow;
using PHSRAG.Insight21.Policy;
using PHSRAG.Insight21.SearchContext;
using PHSRAG.Utility;
using WorkFlow = PHSRAG.Insight21.InsightWorkFlow;
using Utils = PHSRAG.Insight21.InsightUtilities;

namespace PHSRAG.Insight21.Humans
{
    /// <summary>
    /// This page is called from Humans Activitylist tab. This page has a list of activity list on which 
    /// logged in user needs to act. This list gets generated from Skelta Activity List table.
    /// Users can take a look at their outstanding work on which they need to take action from this page.
    /// They can select one of the outstanding processes from the page and go to Workflow detail page 
    /// to work on it. 
    /// </summary>
    public partial class WorkFlowActivity : BasePage
    {
        #region Private Constants

        private const string CurrentPageIndexKey = "CurrentPageIndexKey_7623A980-6761-44d3-BE97-0838357DC385";
        private const int ItemsPerPage = 20;
        private const string PageName = "Activity List";

        #endregion

        #region Private Variables		

        private ICachePolicy cachePolicy;
        private string moduleType = string.Empty;
        private ICachePolicy pageCachePolicy;
        private string protocolNumber = string.Empty;
        private string protocolTitle = string.Empty;
        //Boolean variable reprsenting the retrieval of search criteria
        private bool retrievedSearchCriteria;
        private string workflowActivityPageKey = "workflowActivityPageKey_C88C9659-1AA8-435f-83BB-FBCABDDC3B70";

        #endregion

        #region ColumnIndex Enum

        /// <summary>
        /// Provides indexes used in the datagrid for specific columns
        /// </summary>
        private enum ColumnIndex
        {
            /// <summary>Protocol ID column index (hidden)</summary>
            ProtocolID,
            /// <summary>PRotocol Process ID column index (hidden)</summary>
            ProtocolProcessID,
            /// <summary>access level column index (hidden)</summary>
            ///AccessLevel,
            /// <summary>protocol # column index</summary>
            ProtocolNumber,
            /// <summary>protocol title column index</summary>
            ProtocolTitle,
            /// <summary>type column undex</summary>
            Type,
            /// <summary>pi's name column index</summary>
            PIName,
            /// <summary>Action needed column index</summary>
            NeededAction,
            /// <summary>Date assigned column index</summary>
            DateAssigned,
            /// <summary>Access level column index</summary>
            AccessLevel,
            /// <summary>Work Flow execi=utionId Column index</summary>
            WFExecutionId // hidden
        }

        #endregion

        #region Web Form Designer generated code

        protected override void OnInit(EventArgs e)
        {
            //
            // CODEGEN: This call is required by the ASP.NET Web Form Designer.
            //
            InitializeComponent();
            base.OnInit(e);

            cachePolicy = (Policy.ICachePolicy) Session[Policy.Names.CachePolicyKey];
            pageCachePolicy = (Policy.ICachePolicy) Session[Policy.Names.PageCachePolicyKey];

            humansSubNavigation.Navigate += new CommandEventHandler(OnSubNavigate);
            this.downloadBar.FailedAction += new CommandEventHandler(OnDownloadFailed);
        }

        /// <summary>
        /// Required method for Designer support - do not modify
        /// the contents of this method with the code editor.
        /// </summary>
        private void InitializeComponent()
        {
            this.header.Navigate += new System.Web.UI.WebControls.CommandEventHandler(this.OnNavigate);
            this.workflowActivityList.ItemCreated += new System.Web.UI.WebControls.DataGridItemEventHandler(this.OnItemCreated);
            this.workflowActivityList.ItemCommand += new System.Web.UI.WebControls.DataGridCommandEventHandler(this.OnItemCommand);
            this.workflowActivityList.PageIndexChanged += new System.Web.UI.WebControls.DataGridPageChangedEventHandler(this.OnPageIndexChanged);
            this.workflowActivityList.SortCommand += new System.Web.UI.WebControls.DataGridSortCommandEventHandler(this.OnSort);
            this.workflowActivityList.ItemDataBound += new System.Web.UI.WebControls.DataGridItemEventHandler(this.OnItemDataBound);
            this.Load += new System.EventHandler(this.OnPageLoad);
            this.topPager.FirstPage += new System.Web.UI.WebControls.CommandEventHandler(this.OnFirstPage);
            this.topPager.PreviousPage += new System.Web.UI.WebControls.CommandEventHandler(this.OnPreviousPage);
            this.topPager.NextPage += new System.Web.UI.WebControls.CommandEventHandler(this.OnNextPage);
            this.topPager.LastPage += new System.Web.UI.WebControls.CommandEventHandler(this.OnLastPage);
            this.bottomPager.FirstPage += new System.Web.UI.WebControls.CommandEventHandler(this.OnFirstPage);
            this.bottomPager.PreviousPage += new System.Web.UI.WebControls.CommandEventHandler(this.OnPreviousPage);
            this.bottomPager.NextPage += new System.Web.UI.WebControls.CommandEventHandler(this.OnNextPage);
            this.bottomPager.LastPage += new System.Web.UI.WebControls.CommandEventHandler(this.OnLastPage);
            this.breadCrumb.Navigate += new CommandEventHandler(OnNavigate);
        }

        #endregion

        #region Private Properties			

        /// <summary>
        /// ReadOnly property to get HumansWorkFlow helper object. This object gets loaded if it is not cached. Otherwise it get loaded
        /// and gets cached. This object is used to load the grid on the page.
        /// </summary>
        private HumansWorkFlow HumansWorkflow
        {
            get
            {
                HumansWorkFlow humansWF = cachePolicy.GetCachedObject(HumansWorkFlow.CacheKey) as HumansWorkFlow;

                if (humansWF == null)
                {
                    humansWF = new HumansWorkFlow(cachePolicy);
                    UserContext userContext = cachePolicy.GetCachedObject(UserContext.CacheKey) as UserContext;
                    object[] args = {userContext.Username, userContext.DomainUserId, ModuleType};
                    humansWF.Load(DataAccess.ConnectionString, null, args);
                    humansWF.Cache();
                }
                return humansWF;
            }
        }

        /// <summary>
        /// ReadOnly property to get module type that is to be passed in as a parameter to the load method
        /// </summary>
        private string ModuleType
        {
            get
            {
                if (moduleType == string.Empty)
                {
                    moduleType = (header.ModuleName.ToLower() == "animals") ? "A" : "H";
                }

                return moduleType;
            }
        }

        /// <summary>
        /// Get/Set the current page within the datagrid for display. This information persists across page loads.
        /// </summary>
        private int CurrentPageIndex
        {
            get
            {
                Hashtable h = pageCachePolicy.GetCachedObject(workflowActivityPageKey) as Hashtable;
                return (h == null || h[CurrentPageIndexKey] == null) ? 0 : (int) h[CurrentPageIndexKey];
            }
            set
            {
                Hashtable h = pageCachePolicy.GetCachedObject(workflowActivityPageKey) as Hashtable ?? new Hashtable();
                h[CurrentPageIndexKey] = value;
                workflowActivityList.CurrentPageIndex = value;
                pageCachePolicy.Cache(workflowActivityPageKey, h);
            }
        }

        #endregion

        # region Get/Set property for search criteria 

        /// <summary>
        /// Get/Set the Protocol Number from/to search control
        /// </summary>
        private string ProtocolNumber
        {
            get
            {
                GetSearchCriteria();
                return protocolNumber ?? "";
            }
            set { protocolNumber = value; }
        }

        /// <summary>
        /// Get/Set the Protocol Title from/to search control
        /// </summary>
        private string ProtocolTitle
        {
            get
            {
                GetSearchCriteria();
                return protocolTitle ?? "";
            }
            set { protocolTitle = value; }
        }

        #endregion

        #region Events

        /// <summary>
        /// Loads the page. Loads HumanWorkflow object, loads grid with protocol processes. 
        /// Sets pagination and navigation links.		
        /// </summary>
        /// <param name="sender">Sender of the event</param>
        /// <param name="e">Argument associated with the event</param>
        protected void OnPageLoad(object sender, EventArgs e)
        {
            breadCrumb.Add(
                "Activity List",
                "WorkFlowActivity.aspx",
                Settings.GetKeyValue("BreadCrumb.Humans.ActivityList", 1));
            SetHumansOrAnimalsControls();
            if (!IsPostBack && postbackGuard.IsValid)
            {
                workflowActivityList.PageSize = Settings.GetKeyValue("HumansDataGrid.ItemsPerPage", ItemsPerPage);
                CommonSearchContext searchContext = cachePolicy.GetCachedObject(CommonSearchContext.CacheKey) as CommonSearchContext;

                if (searchContext != null)
                {
                    UserContext userContext = (UserContext) cachePolicy.GetCachedObject(UserContext.CacheKey);
                    object[] args = {userContext.Username, userContext.DomainUserId, ModuleType};
                    HumansWorkflow.Load(DataAccess.ConnectionString, searchContext.GetSearchCriteria(Page.Request.Url.ToString()), args);
                }
                //humansSubNavigation.SelectedLink = "Activity List";
            }
            if (CurrentPageIndex == 0)
            {
                InitializePager();
            }
            LoadDataGrid();
            ManagePagination();
            ManageNavigationLinks();
        }

        /// <summary>
        /// Handler for the event raised by the CommonSearch control when the "Clear Selection" buttion is clicked upon.
        /// The control clears the criteria (specific to this module).
        /// Since in the page life-cycle, the Load occurs before the Clear event, we have to instigate a re-load of the
        /// data grid to refelect the fact that the search criteria has been cleared.
        /// </summary>
        /// <param name="sender">Sender of the event</param>
        /// <param name="e">Argument associated with the event</param>
        protected void OnClearSelection(object sender, CommandEventArgs e)
        {
            PerformSearch();
        }

        /// <summary>
        /// Initiates the search by calling PerformSearch
        /// </summary>
        /// <param name="args">Argument associated with the event (contains the search criteria dictionary)</param>
        protected void OnSearch(SearchCriteriaArgs args)
        {
            PerformSearch();
        }

        /// <summary>
        /// This event gets called when Protocol Title column gets clicked on the grid.
        /// This is used to select one of the rows on the grid and go to Workflow detail screen to act on that selected item.
        /// </summary>
        /// <param name="source">Sender of the event</param>
        /// <param name="e">Argument associated with the event</param>
        private void OnItemCommand(object source, DataGridCommandEventArgs e)
        {
            try
            {
                if ((e.Item.ItemType == ListItemType.Item) || (e.Item.ItemType == ListItemType.AlternatingItem))
                {
                    if (e.CommandName == "SelectWFDetail")
                    {
                        Hashtable outgoingData = new Hashtable();
                        outgoingData.Add(Keys.ProtocolIdKey, e.Item.Cells[(int) ColumnIndex.ProtocolID].Text);
                        outgoingData.Add(Keys.ProtocolProcessIdKey, e.Item.Cells[(int) ColumnIndex.ProtocolProcessID].Text);
                        outgoingData.Add(Keys.WFExecutionIdKey, e.Item.Cells[(int) ColumnIndex.WFExecutionId].Text);
                        outgoingData.Add(Keys.ProtocolAccessKey, e.Item.Cells[(int) ColumnIndex.AccessLevel].Text);
                        outgoingData.Add(Keys.WFNeededActionKey, e.Item.Cells[(int)ColumnIndex.NeededAction].Text);
                        //Cache this Object as we will need it in the Workflow detail page.						
                        ProtocolProcess protocolProcess = ProtocolProcess.GetProtocolProcess(
                            DataAccess.GetConnectionString(), Int32.Parse(e.Item.Cells[(int) ColumnIndex.ProtocolProcessID].Text), cachePolicy, null);
                        //pp.Load(DataAccess.ConnectionString,Int32.Parse(e.Item.Cells[(int) ColumnIndex.ProtocolProcessID].Text));
                        cachePolicy.Cache(Keys.ProtocolProcessKey, protocolProcess);
                        pageCachePolicy.Cache(Keys.IncomingDataKey, outgoingData);

                        PurgeCache();
                        Response.Redirect(Settings.GetKeyValue("SubModuleNavigation.Humans.WorkflowURL", ""), false);
                    }
                }
            }
            catch (Exception ex)
            {
                annunciator.Message =
                    String.Format("{0} while attempting to transfer to page {1}, ProtocolID =  {2}",
                        ExceptionReport.GetExceptionInfo(ex, false),
                        Settings.GetKeyValue("SubModuleNavigation.Humans.ProtocolDetailsURL", ""));
            }
        }

        /// <summary>
        /// Thi method will set the appropriate Humans/Animals tab.
        /// </summary>
        private void SetHumansOrAnimalsControls()
        {
            if (ModuleType == "H")
            {
                humansSubNavigation.Visible = true;
                animalsSubNavigation.Visible = false;
                humansSubNavigation.SelectedLink = PageName;
            }
            else
            {
                animalsSubNavigation.Visible = true;
                humansSubNavigation.Visible = false;
                animalsSubNavigation.SelectedLink = PageName;
            }
        }

        /// <summary>
        /// Occurs when the FirstPage hyperlink is clicked on the pager.
        /// The page's DataGrid is reloaded with the data belonging to the first page.
        /// </summary>
        /// <param name="sender">The object raising an event.</param>
        /// <param name="e">Argument associated with the event</param>
        private void OnFirstPage(object sender, CommandEventArgs e)
        {
            CurrentPageIndex = 0;
            ManagePagination();
            LoadDataGrid();
            ManageNavigationLinks();
        }

        /// <summary>
        /// Occurs when the LastPage hyperlink is clicked on the pager.
        /// The page's DataGrid is reloaded with the data belonging to the last page.
        /// </summary>
        /// <param name="sender">The object raising an event.</param>
        /// <param name="e">Argument associated with the event</param>
        private void OnLastPage(object sender, CommandEventArgs e)
        {
            CurrentPageIndex = topPager.PageCount - 1;
            ManagePagination();
            LoadDataGrid();
            ManageNavigationLinks();
        }

        /// <summary>
        /// Occurs when the NexttPage hyperlink is clicked on the pager.
        /// The page's DataGrid is reloaded with the data belonging to the next page.
        /// </summary>
        /// <param name="sender">The object raising an event.</param>
        /// <param name="e">Argument associated with the event</param>
        private void OnNextPage(object sender, CommandEventArgs e)
        {
            ++CurrentPageIndex;
            ManagePagination();
            LoadDataGrid();
            ManageNavigationLinks();
        }

        /// <summary>
        /// Occurs when the PreviousPage hyperlink is clicked on the pager.
        /// The page's DataGrid is reloaded with the data belonging to the previous page.
        /// </summary>
        /// <param name="sender">The object raising an event.</param>
        /// <param name="e">Argument associated with the event</param>
        private void OnPreviousPage(object sender, CommandEventArgs e)
        {
            --CurrentPageIndex;
            ManagePagination();
            LoadDataGrid();
            ManageNavigationLinks();
        }

        /// <summary>
        /// This event is raised when the page index property is changed on the pager control.
        /// The page's DataGrid is reloaded with the data belonging to page specified by the index.
        /// </summary>
        /// <param name="source">The object raising an event.</param>
        /// <param name="e">Argument associated with the event</param>
        private void OnPageIndexChanged(object source, DataGridPageChangedEventArgs e)
        {
            workflowActivityList.CurrentPageIndex = e.NewPageIndex;
            ManagePagination();
            LoadDataGrid();
            ManageNavigationLinks();
        }

        /// <summary>
        /// Handles events raised by sorting the datagrid.
        /// </summary>
        /// <param name="source">The object raising an event.</param>
        /// <param name="e">Argument associated with the event</param>
        private void OnSort(object source, DataGridSortCommandEventArgs e)
        {
            if (e.SortExpression != string.Empty)
            {
                HumansWorkflow.Sort(e.SortExpression);
                ManagePagination();
                LoadDataGrid();
                ManageNavigationLinks();
            }
        }

        /// <summary>
        /// Resets the subnavigation selected link(s) before the 
        /// header performs a redirect.
        /// </summary>
        /// <param name="sender">Control which rasied the event.</param>
        /// <param name="e">Arguments associated with the event.</param>
        protected void OnHeaderNavigate(object sender, CommandEventArgs e)
        {
            PurgeCache();
            humansSubNavigation.Reset();
        }

        /// <summary>
        /// Purges the cache before the humans subnavigation header performs a redirect.
        /// </summary>
        /// <param name="sender">Control which rasied the event.</param>
        /// <param name="e">Arguments associated with the event.</param>
        protected void OnSubNavigate(object sender, CommandEventArgs e)
        {
            PurgeCache();
        }

        /// <summary>
        /// During data binding of the grid, a tooltip with the full title is associated with the
        /// shortened version that appears on the screen.  For every record, the corresponding lock/unlock
        /// </summary>
        /// <param name="sender">The object raising an event.</param>
        /// <param name="e">Argument associated with the event</param>
        private void OnItemDataBound(object sender, DataGridItemEventArgs e)
        {
            try
            {
                if ((e.Item.ItemType == ListItemType.Item ||
                    e.Item.ItemType == ListItemType.AlternatingItem))
                {
                    e.Item.Cells[(int) ColumnIndex.ProtocolTitle].ToolTip = e.Item.Cells[(int) ColumnIndex.ProtocolTitle].Text;
                }
            }
            catch (Exception ex)
            {
                ExceptionReport.WriteToEventLog("Error occurred while trying to bind the data to the grid", ex, true, ExceptionReport.ReportType.Error);
                annunciator.Message = "Error occurred while trying to bind the data to the grid";
            }
        }

        /// <summary>
        /// Handler for event raised while each data grid item is created.
        /// If the item being created is the data grid header, do the following:
        /// Add the appropriate sort symbol to denote ascending/descending sequence for the current sort column.
        /// This requires us to locate the cell which corresponding to the column within the collection of TableCell
        /// maintained by the DataGridItem which is under creation. That collection is indexed numerically, the value being
        /// the position of the column within the columns collection maintained by the data grid.
        /// One simple way to do this is to create static mapping between the name of the column and its index. However, this
        /// suffers from the shortcoming that if the sequence of columns is changed on the page, the static binding MUST
        /// be changed too. If they get out of sync, we would be sorting on inappropriate columns!
        /// To avoid this, and to render the code independent of how the page gets managed, we will build a Hashtable of
        /// column indeces, keyed by the sort expression of each column. That way, we could do a quick lookup to get the
        /// index of a column and set the sort symbol on that column.
        /// If the item being created is a data row item, disable its view state.
        /// </summary>
        /// <param name="sender">Control which raised the event</param>
        /// <param name="e">Argument associated with the event</param>
        private void OnItemCreated(object sender, DataGridItemEventArgs e)
        {
            try
            {
                if (e.Item.ItemType == ListItemType.Header)
                {
                    HumansWorkFlow humanWorkflow = HumansWorkflow;
                    Label sortSymbol = new Label();
                    sortSymbol.Text = humanWorkflow.SortAscending ? InsightUtilities.Constants.SortAscendingText : InsightUtilities.Constants.SortDescendingText;
                    sortSymbol.Font.Name = InsightUtilities.Constants.SortSymbolFontName;

                    Hashtable columnMap = new Hashtable();
                    foreach (DataGridColumn column in workflowActivityList.Columns)
                    {
                        columnMap[column.SortExpression] = workflowActivityList.Columns.IndexOf(column);
                    }

                    string sortColumn = humanWorkflow.SortColumn;
                    if (columnMap.ContainsKey(sortColumn))
                    {
                        (e.Item.Cells[(int) columnMap[sortColumn]]).Controls.Add(sortSymbol);
                    }
                }
                else if ((e.Item.ItemType == ListItemType.Item) || (e.Item.ItemType == ListItemType.AlternatingItem))
                {
                    e.Item.EnableViewState = false;
                }
            }
            catch (Exception ex)
            {
                ExceptionReport.WriteToEventLog("Error occurred while trying to load the control to the grid", ex, true, ExceptionReport.ReportType.Error);
                annunciator.Message = "Error occurred while trying to load the control";
            }
        }

        /// <summary>
        /// Resets the subnavigation selected link before the header or the breadCrumb performs a redirect.
        /// </summary>
        /// <param name="sender">Control which rasied the event.</param>
        /// <param name="e">Arguments associated with the event.</param>
        private void OnNavigate(object sender, CommandEventArgs e)
        {
            PurgeCache();
            humansSubNavigation.Reset();
        }

        #endregion

        #region Private Methods

        /// <summary>
        /// Initilize the first record, last record and current page values for the pager controls.
        /// Set the current page index to 0 and manage navigation links.
        /// </summary>
        private void InitializePager()
        {
            bottomPager.FirstRecord = topPager.FirstRecord = 1;
            bottomPager.LastRecord = topPager.LastRecord =
                Math.Min(workflowActivityList.PageSize, workflowActivityList.Items.Count);
            bottomPager.CurrentPage = topPager.CurrentPage = 1;
            CurrentPageIndex = 0;
            ManageNavigationLinks();
        }

        /// <summary>
        /// Pagination management
        /// </summary>
        private void ManagePagination()
        {
            int currentPageIndex = CurrentPageIndex;
            workflowActivityList.CurrentPageIndex = currentPageIndex;

            int startIndex = currentPageIndex*workflowActivityList.PageSize;
            bottomPager.FirstRecord = topPager.FirstRecord = startIndex + 1;

            int lastRecord = HumansWorkflow.ActivityCount; //searchInEffect ? WorkInProgressProtocolProcesses.FilteredCount : 
            bottomPager.LastRecord = topPager.LastRecord =
                Math.Min(startIndex + workflowActivityList.PageSize, lastRecord);
        }

        /// <summary>
        /// Enables or Disables links to other pages within the grid
        /// </summary>
        private void ManageNavigationLinks()
        {
            bottomPager.EnableFirstPage = topPager.EnableFirstPage =
                bottomPager.EnablePreviousPage = topPager.EnablePreviousPage =
                    (workflowActivityList.CurrentPageIndex != 0);

            bottomPager.EnableLastPage = topPager.EnableLastPage =
                bottomPager.EnableNextPage = topPager.EnableNextPage =
                    (workflowActivityList.CurrentPageIndex != (topPager.PageCount - 1));
        }

        /// <summary>
        /// Retrieves the CommonSearchContext from the cache and
        /// performs a Protocol Process search.
        /// </summary>
        private void PerformSearch()
        {
            CommonSearchContext searchContext = cachePolicy.GetCachedObject(CommonSearchContext.CacheKey) as CommonSearchContext;
            if (searchContext != null)
            {
                UserContext userContext = (UserContext) cachePolicy.GetCachedObject(UserContext.CacheKey);
                object[] args = {userContext.Username, userContext.DomainUserId, ModuleType};
                HumansWorkflow.Load(DataAccess.ConnectionString, searchContext.GetSearchCriteria(Page.Request.Url.ToString()), args);
                CurrentPageIndex = 0;

                LoadDataGrid();
                InitializePager();
            }
        }

        /// <summary>
        /// Obtains all the search criteria that has been entered into the search control
        /// </summary>
        private void GetSearchCriteria()
        {
            if (!retrievedSearchCriteria)
            {
                CommonSearchContext searchContext = cachePolicy.GetCachedObject(CommonSearchContext.CacheKey) as CommonSearchContext;

                if (searchContext != null)
                {
                    SearchCriteria searchCriteria = searchContext.GetSearchCriteria(Page.Request.Url.ToString());

                    if (searchCriteria.Count > 0)
                    {
                        foreach (string key in searchCriteria.Keys)
                        {
                            if (key.Trim().ToLower() == InsightUtilities.Constants.PrimaryProtocolSearch.ProtocolNumberKey)
                            {
                                ProtocolNumber = searchCriteria[key];
                            }
                            else if (key.Trim().ToLower() == InsightUtilities.Constants.PrimaryProtocolSearch.ProtocolTitleKey)
                            {
                                ProtocolTitle = searchCriteria[key];
                            }
                        }
                    }
                }
            }
            retrievedSearchCriteria = true;
        }

        /// <summary>
        /// This method gets called from page load as well as from pagination events, sorting and searching controls.
        /// This method binds data to the grid and also take care of pagination calculation.
        /// </summary>
        private void LoadDataGrid()
        {
            HumansWorkFlow humansWF = HumansWorkflow;
            workflowActivityList.VirtualItemCount = bottomPager.RecordCount = topPager.RecordCount =
                humansWF.ActivityCount;
            int currentPageIndex = CurrentPageIndex;
            int pageCount = (topPager.RecordCount/workflowActivityList.PageSize) +
                (((topPager.RecordCount%workflowActivityList.PageSize) == 0) ? 0 : 1);
            bottomPager.PageCount = topPager.PageCount = pageCount;
            bottomPager.CurrentPage = topPager.CurrentPage = currentPageIndex + 1;
            DataTable wfActivityTable = humansWF.GetWorkflowActivityList(
                currentPageIndex*workflowActivityList.PageSize, workflowActivityList.PageSize);
            workflowActivityList.DataSource = wfActivityTable;
            workflowActivityList.DataBind();

            if (wfActivityTable.Rows.Count == 0)
            {
                gridContainer.Visible = false;
                annunciator.Message = "The search criteria yielded no results.";
            }
            else
            {
                gridContainer.Visible = true;
                annunciator.Message = string.Empty;
                recordCount.Text = topPager.RecordCount.ToString();
            }
        }

        /// <summary>
        /// Invoked by the download bar when it catches an exception.
        /// </summary>
        /// <param name="sender">Control which raised the event</param>
        /// <param name="e">Argument associated with the event</param>
        private void OnDownloadFailed(object sender, CommandEventArgs e)
        {
            annunciator.Title = "Following error(s) occurred while downloading";
            annunciator.Message = ExceptionReport.GetExceptionInfo((Exception) e.CommandArgument, false);
        }

        /// <summary>
        /// Uncaches all objects with data for this page.
        /// </summary>
        private void PurgeCache()
        {
            System.Diagnostics.Trace.WriteLine("Purging ExemptProtocols...");
            HumansWorkflow.Purge();
            cachePolicy.UnCache(HumansWorkFlow.CacheKey);
        }

        #endregion
    }
}